#include "NessEngineSys.h"

NessEngineSys::NessEngineSys(){
	sysDone=false;
	//timer init stuffz
	startTicks=0;
	pausedTicks=0;
	paused = false;
	started = false;
}
NessEngineSys::~NessEngineSys(){}

//setup SDL window
bool NessEngineSys::InitSystem(int width, int height){
	
	if(SDL_Init(SDL_INIT_EVERYTHING)<0)
		return false;
	
	if(SDL_SetVideoMode(width, height, 32, SDL_OPENGL)==NULL)
		return false;
	
	wWidth=width;
	wHeight=height;

	if(!InitGL())
		return false;

	return true;
}

//initialize OpenGL
bool NessEngineSys::InitGL(){

	glClearColor(0,0,0,0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0,wWidth,wHeight,0,-1,1);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	if(glGetError()!=GL_NO_ERROR)
		return false;

	return true;
}


//update SDL events and clear color buffer
void NessEngineSys::UpdateEvents(){
	StartFPS();
	//update window events
	while(SDL_PollEvent(&event)){
		if(event.type==SDL_QUIT)
			sysDone=true;
	}
	key = SDL_GetKeyState(NULL);
	//clear buffer
	glClear(GL_COLOR_BUFFER_BIT);
}

//swap the buffers to refresh the screen
void NessEngineSys::UpdateSystem(int framesPerSecond){
	SDL_GL_SwapBuffers();
	if(GetTicks()<1000/framesPerSecond)
		SDL_Delay((1000/framesPerSecond)-GetTicks());
}

void NessEngineSys::Render(Entity *entity){
	if(entity->texture.texture){
		if(entity->tileSheet==true){
			Render(entity->texture,entity->GetX(),entity->GetY(),
				entity->GetW(),entity->GetH(),entity->totalFrames,entity->frame);
		}
		else if(entity->tileSheet==false){
			Render(entity->texture,entity->GetX(),entity->GetY(),
				entity->GetW(),entity->GetH());
		}
	}
	else
		Render(entity->GetX(),entity->GetY(),entity->GetW(),entity->GetH());
}

//render function that takes a GLuint argument
//to render any texture
void NessEngineSys::Render(GLfloat x, GLfloat y, GLfloat w, GLfloat h){
	float tx =  -w/2;
	float ty =  -h/2;
	glEnable(GL_TEXTURE_2D);

	glBegin(GL_QUADS);
		glVertex2f(tx,ty);
		glVertex2f(tx+w,ty);
		glVertex2f(tx+w,ty+h);
		glVertex2f(tx,ty+h);
	glEnd();

	glLoadIdentity();
		
}
//render un-animated texture
void NessEngineSys::Render(NessTexture Tex, GLfloat x, GLfloat y, GLfloat w, GLfloat h){
	float tx =  -w/2;
	float ty =  -h/2;
	glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, Tex.texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glColor3f(1.0f, 1.0f, 1.0f);
	glBegin(GL_QUADS);
		//glVertex2f(tx,ty);
		glTexCoord2f(0.0f,0.0f);
		glVertex2f(tx,ty);
		glTexCoord2f(1.0f,0.0f);
		glVertex2f(tx+w,ty);
		glTexCoord2f(1.0f,1.0f);
		glVertex2f(tx+w,ty+h);
		glTexCoord2f(0.0f,1.0f);
		glVertex2f(tx,ty+h);
	glEnd();
	glBindTexture(GL_TEXTURE_2D,NULL);
	glLoadIdentity();
}
//render animated texture
void NessEngineSys::Render(NessTexture Tex, GLfloat x, GLfloat y, GLfloat w, GLfloat h, 
						  GLfloat totalFrames, GLfloat Frame){
	
	//division of columns and rows
	GLfloat xdivision = 1.0f/totalFrames;

	float tx =  -w/2;
	float ty =  -h/2;
	GLfloat xcell = Frame*xdivision;
	GLfloat xcell2 = (Frame*xdivision)+xdivision;
	glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, Tex.texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glColor3f(1.0f, 1.0f, 1.0f);
	glBegin(GL_QUADS);
		glTexCoord2f(xcell,0.0f);
		glVertex2f(tx,ty);
		glTexCoord2f(xcell2,0.0f);
		glVertex2f(tx+w,ty);
		glTexCoord2f(xcell2,1.0f);
		glVertex2f(tx+w,ty+h);
		glTexCoord2f(xcell,1.0f);
		glVertex2f(tx,ty+h);
	glEnd();

	glLoadIdentity();
}

void NessEngineSys::StartMatrix(Entity *entity){
	glPushMatrix();
	glTranslatef(entity->GetX(),entity->GetY(),0);
}

void NessEngineSys::EndMatrix(){
	glPopMatrix();
}

void NessEngineSys::RotateEntity(Entity *entity, float angle){
	glRotatef(angle, 0, 0, 1);
}

//timer functions
void NessEngineSys::StartFPS(){
	started = true;
	paused = false;
	startTicks = SDL_GetTicks();
}

void NessEngineSys::StopFPS(){
	started = false;
	paused = false;
}

void NessEngineSys::PauseFPS(){
	if((started == true) && (!paused)){
        paused = true;
        pausedTicks = SDL_GetTicks() - startTicks;
    }
}

void NessEngineSys::UnPauseFPS(){
    if(paused == true){
        paused = false;
        startTicks = SDL_GetTicks() - pausedTicks;
        pausedTicks = 0;
    }
}

int NessEngineSys::GetTicks(){
		if(started == true){
        if(paused == true)
            return pausedTicks;
        else
            return SDL_GetTicks() - startTicks;
    }
    return 0;
}

bool NessEngineSys::IsStarted(){
	return started;
}

bool NessEngineSys::IsPaused(){
	return paused;
}

bool NessEngineSys::EntityCollision(Entity *a, Entity *b){

	SDL_Rect A;
	SDL_Rect B;
	A.x = a->box.x-(a->box.w/2);
	B.x = b->box.x-(b->box.w/2);
	A.y = a->box.y-(a->box.h/2);
	B.y = b->box.y-(b->box.h/2);
	A.w = a->box.w;
	B.w = b->box.w;
	A.h = a->box.h;
	B.h = b->box.h;

	//rectangle sides
    int leftA, leftB;
    int rightA, rightB;
    int topA, topB;
    int bottomA, bottomB;
    //calculate the sides of rect A
    leftA = A.x;
    rightA = A.x + A.w;
    topA = A.y;
    bottomA = A.y + A.h;
    //calculate the sides of rect B
    leftB = B.x;
    rightB = B.x + B.w;
    topB = B.y;
    bottomB = B.y + B.h;
    //if any of the sides from A are outside of B
    if( bottomA < topB )
    {
        return false;
    }
    if( topA > bottomB )
    {
        return false;
    }
    if( rightA < leftB )
    {
        return false;
    }
    if( leftA > rightB )
    {
        return false;
    }
    //if none of the sides from A are outside B
    return true;

}